package pl.edu.agh.gronoMining.frequentSubgraphFinder.frequentSearcher;

import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import org.apache.log4j.Logger;

import pl.edu.agh.gronoMining.frequentSubgraphFinder.graph.Graph;
import pl.edu.agh.gronoMining.frequentSubgraphFinder.graph.GraphException;
import pl.edu.agh.gronoMining.frequentSubgraphFinder.graph.Node;
import pl.edu.agh.gronoMining.frequentSubgraphFinder.strategy.Strategy;

/**
 * Basic class called in frequent subgraph mining algorithm
 */
public class Miner {
	
	private static Logger logger = Logger.getLogger(Miner.class);

	private Graph inputGraph;
	private Strategy strategy;
	private Properties properties;
	
	/**
	 * @param inputGraph input graph
	 * @param strategy strategy
	 * @param properties properties
	 */
	public Miner(Graph inputGraph, Strategy strategy, Properties properties) {
		this.inputGraph = inputGraph;
		this.strategy = strategy;
		this.properties = properties;
	}
	
	/**
	 * perform frequent subgraph mining
	 * @return set of found frequent subgraphs
	 */
	public Set<Graph> startMining() {
		
		logger.info("start mining");
		
			// check if 'isTree' property
		boolean isTree = false;
		if (this.properties.get("isGraphTree").equals("true"))
			isTree = true;
		
			// generate number of start nodes
		Set<Node> startNodes = this.getStartNodes();
		int startNodesNumber = startNodes.size();
		logger.info("found " + startNodesNumber + " start nodes");
		
			// calculate minimum graphs number to be frequent
		int minimumFrequency = this.calculateMinimumFrequency(startNodesNumber);
		logger.info("there must be at least " + minimumFrequency + " subgraphs to be frequent");
		
			// perform frequent subgraph mining
		Set<Graph> resultSet = null;
		long startTime = System.currentTimeMillis();
		try {
			FrequentGraphsMiner frequentMiner = new FrequentGraphsMiner(this.inputGraph, this.strategy, minimumFrequency, isTree);
			resultSet = frequentMiner.startMining();
		} catch (GraphException e) {
			e.printStackTrace();
		}
		long endTime = System.currentTimeMillis();
		
			// calculate time
		long time = endTime - startTime;
		logger.info("end mining in "+((float) time)/1000+"s");
		
		return resultSet;
	}
	
	/**
	 * @return all start nodes in input graph
	 */
	private Set<Node> getStartNodes() {
		Set<Node> startNodes = new HashSet<Node>();
		for (Node node : inputGraph.getAllNodes()) {
			if (node.getType() == strategy.getStartType())
				startNodes.add(node);
		}
		return startNodes;
	}
	
	/**
	 * Calculate minimum number of subgraph to be frequent
	 * @param startNodesNumber number of start nodes
	 * @return minimum number of subgraph to be frequent
	 */
	private int calculateMinimumFrequency(int startNodesNumber) {
		String minimumFrequenciesString = properties.getProperty("minimumFrequencies");
		if (minimumFrequenciesString.charAt(minimumFrequenciesString.length() - 1) == '%') {
			String minimumFrequenciesValueString = minimumFrequenciesString.substring(0, minimumFrequenciesString.length() - 1);
			int minimumFrequencies = Integer.parseInt(minimumFrequenciesValueString);
			return (int) ((float) startNodesNumber * ((float) minimumFrequencies / 100.0));
		}
		else
			return Integer.parseInt(minimumFrequenciesString);
	}
	
}
